package 
{	
	import com.util.Camera;
	
	import feathers.display.TiledImage;
	
	import flash.geom.Rectangle;
	
	import levelloader.LayerData;
	import levelloader.TileData;
	import levelloader.TiledMap;
	
	import starling.display.Image;

	public class GameLayer extends GameObject
	{	
		protected var layer:LayerData;
		protected var mapWidth:uint;
		protected var mapHeight:uint;
		protected var tileWidth:uint;
		protected var tileHeight:uint;
		
		protected var camPosX:uint;
		protected var camPosY:uint;
		protected var camWidth:uint;
		protected var camHeight:uint;
		protected var camWidthTiles:int
				
		protected var leftColumnIndex:uint;		
		protected var rightColumnIndex:uint;
		
		protected var _parallaxRatio:Number;
		
		protected var _parent:World;
		protected var _layerID:uint;
		
		protected var map:TiledMap;

		public function GameLayer(world:World, layerID:uint, parallaxRatio:Number)
		{
			super();						
			
			_parallaxRatio = parallaxRatio;
			_parent = world;
			_layerID = layerID;
			map = _parent.getTMXTileMap();
			
			layer = map.layers()[layerID];
			var rect:Rectangle = Camera.defaultCameraRect();			
			
			mapWidth = map.mapWidth();
			mapHeight = map.mapHeight();
			tileWidth = map.tileWidth();
			tileHeight = map.tileHeight();
			
			camWidth = rect.width;
			camHeight = rect.height;
			camPosX = rect.left;
			camPosY = rect.top;
			
			camWidthTiles = camWidth/tileWidth;
			var tileStartIndex:int = Math.floor(camPosX/tileWidth);
			var tileMaxHorizontalIndex:int = tileStartIndex + camWidthTiles-1;
			
			leftColumnIndex = 0;
			rightColumnIndex = camWidthTiles - 1;
			
			renderView();
		}
		
		public override function onEnterFrame(dt:Number):void
		{
			var camX:Number = _parent.camera.getCameraPosX(_parallaxRatio);
			var camY:Number = _parent.camera.getCameraPosY(_parallaxRatio);
			
			var currentLeftIndex:uint = Math.floor(camX/tileWidth);
			var currentRightIndex:uint = Math.ceil((camX+camWidth-1)/tileWidth);
						
			if(currentLeftIndex > leftColumnIndex)
			{
				leftColumnIndex = currentLeftIndex;
				
				var dropPool:Vector.<TileImage> = new Vector.<TileImage>();
				var child:TileImage;
				var numChild:int = this.numChildren;				
				//check if objects in view are still visible after the last 
				//camera update. If not, then remove these from the display tree.
				for(var id:int = 0; id < numChild; ++id)
				{							
					child = this.getChildAt(id) as TileImage;
					
					if(child != null)
					{
						if(!child.intersectsLine(camX, camX+camWidth-1))
						{
							//Don't delete the elements while iterating the collection. 
							//Mark the objects for deletion by adding them to a temp pool.
							dropPool.push(child);
						}										
					}					
				}	
				//iterate over the temp pool and delete all the objects
				var numDropObjs:uint = dropPool.length;			
				for (var dID:uint = 0; dID < numDropObjs; ++dID)
				{
					dropPool[dID].removeFromParent(true);
				}				
			}
				
			//iterate through the general layer data and 
			//add new objects that are visible from the camera 
			//to this layer's display tree.			
			if(currentRightIndex < mapWidth && currentRightIndex > rightColumnIndex)
			{
				rightColumnIndex = currentRightIndex;
				
				var dataColumn:Vector.<TileData> = layer.getData()[rightColumnIndex];
				renderColumn(dataColumn);
			}
			
			//transform the layer from world space to view space.
			this.x = -camX;
			this.y = -camY;			
		}
		
		protected function renderView():void
		{
			for(var rowIdx:int = 0; rowIdx < camWidthTiles; ++rowIdx)
			{
				var dataColumn:Vector.<TileData> = layer.getData()[rowIdx];
				renderColumn(dataColumn);				
			}										
		}
		
		protected function renderColumn(dataColumn:Vector.<TileData>):void
		{
			var columnLength:uint = dataColumn.length;
			for (var columnIdx:int = 0; columnIdx < columnLength; ++columnIdx)
			{
				var img:TileImage = new TileImage(Assets.getLevelMapAtlas().getTexture(map.tileMapper[dataColumn[columnIdx].textureID]));
				img.x = dataColumn[columnIdx].tileIndexX * tileWidth;
				img.pivotY = img.height;
				img.y = dataColumn[columnIdx].tileIndexY * tileWidth + tileWidth;					
				addChild(img);						
			}								
		}
							
		public override function dispose():void
		{
			super.dispose();
		}
	}
}